package com.example.onlinemonitoring.comCenter;

import com.alibaba.druid.sql.ast.statement.SQLIfStatement.Else;
import com.example.onlinemonitoring.Util.CRC16;
import com.example.onlinemonitoring.Util.CommPortManager;
import com.example.onlinemonitoring.Util.HexUtil;
import com.example.onlinemonitoring.model.Zxdblqsensor;
import com.example.onlinemonitoring.model.Zxdblqhistory;
import com.example.onlinemonitoring.model.Appdevice;
import com.example.onlinemonitoring.model.Gisblqsensor;
import com.example.onlinemonitoring.serviceImpl.ZxdblqsensorServiceImpl;

import net.sf.jsqlparser.expression.DateTimeLiteralExpression.DateTime;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Scope;
import java.text.ParseException;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.ArrayList;
import java.time.*;
import java.time.format.DateTimeFormatter;

/*中性点避雷器
*/
@Service("zxdblqCom")
@Scope("prototype")
public class ZxdblqCom extends CommPortManager {
    private int cmdtype = 0;
    Date ThunderTime = new Date();
    @Autowired
    private ZxdblqsensorServiceImpl zxdblqsensorServiceImpl;

    @Override
    public void receiveData(String str) {
        if (ad.getCommunicationmode() == 4) {
            // read61850(str);
        } else {
            switch (ad.getBrand()) {
                case "云南德胜":
                    Datayn(str);
                    break;
                case "济钢":
                    Dataother(str);
                    break;
                default:
                    return;
            }
        }
    }

    private void Dataother(String str) {
        try {
            str = str.toUpperCase();
            setText(str);
            // 条件判断自己写
            String addrstr = str.substring(0, 2);
            Integer addr = parseHex4(addrstr);

            // if (!"A6".equals(str.substring(6, 8)))
            // return;
            reSend[addrindex] = 0;
            addrindex++;
            Integer startIndex = 6;// 数据起始位置
            if (str.length() < 10)
                return;
            if (str.length() > 10) {
                float LastWcurrent = 0;
                float LastRcurrent = 0;
                int Thundercount = 0;
                int count = 0;
                int year = 0, month = 0, day = 0, hour = 0, minute = 0, seconds = 0;

                setText("设备返回数据： 站点号：" + ad.getStationid() + " 设备地址：" + addr);
                String blqtip1, blqtip2;

                blqtip1 = str.substring(2, 4);
                blqtip2 = str.substring(4, 8);

                Zxdblqsensor blqsensor = new Zxdblqsensor();
                blqsensor.setStationid(ad.getStationid());
                blqsensor.setDeviceaddr(addr);
                blqsensor.setDevicegroup(ad.getDevicegroup());
                // gisblqsensor.setPointaddr(addr);
                // 查询对象
                Zxdblqsensor record = zxdblqsensorServiceImpl.getModel(blqsensor);
                if (record == null) {
                    setText("当前数据库无监测点：设备地址" + addr);
                }

                if (blqtip1.equals("04")) {
                    // LastWcurrent = parseHex88(str.substring(startIndex, startIndex+=4))/1000;
                    // LastWcurrent = parseHex4(str.substring(startIndex, startIndex+=2)) +
                    // parseHex88(str.substring(startIndex, startIndex+=2))/100;
                    Thundercount = Integer.parseInt(str.substring(startIndex, startIndex += 4), 16);
                    LastWcurrent = parseHex88(str.substring(startIndex, startIndex += 4)) / 1000;
                    LastRcurrent = parseHex88(str.substring(startIndex, startIndex += 4)) / 1000;
                    setText("雷击次数：" + Thundercount + " ");
                    setText("泄露电流：" + LastWcurrent + "mA");
                    setText("阻性电流：" + LastRcurrent + "mA");
                    int Tcount = record.getLastthundercount() == null ? 0 : record.getLastthundercount();
                    // if(Tcount!=Thundercount)
                    // {
                    // cmdtype = 1;
                    // }
                    record.setLastwcurrent(LastWcurrent);
                    record.setLastrcurrent(LastRcurrent);
                    record.setLastthundercount(Thundercount);

                    AddAndUpdate(record);
                }

            } else {
                setText("从设备返回的数据有误！请检查串口！");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            setText("从设备返回的数据有误！请检查串口！");
        }
    }

    private void Datayn(String str) {
        try {
            str = str.toUpperCase();
            setText(str);
            // 条件判断自己写
            String addrstr = str.substring(0, 2);
            Integer addr = parseHex4(addrstr);

            reSend[addrindex] = 0;
            addrindex++;
            Integer startIndex = 6;// 数据起始位置
            if (str.length() < 10)
                return;
            if (str.length() > 10) {
                float LastWcurrent = 0;
                int Thundercount = 0;

                setText("设备返回数据： 站点号：" + ad.getStationid() + " 设备地址：" + addr);
                String blqtip1;

                blqtip1 = str.substring(2, 4);

                Zxdblqsensor blqsensor = new Zxdblqsensor();
                blqsensor.setStationid(ad.getStationid());
                blqsensor.setDeviceaddr(addr);
                blqsensor.setDevicegroup(ad.getDevicegroup());
                Zxdblqsensor record = zxdblqsensorServiceImpl.getModel(blqsensor);
                if (record == null) {
                    setText("当前数据库无监测点：设备地址" + addr);
                }

                if (blqtip1.equals("04")) {
                    Thundercount = Integer.parseInt(str.substring(startIndex, startIndex += 4), 16);
                    LastWcurrent = parsePHex4(str.substring(startIndex, startIndex += 4));
                    setText("放电次数：" + Thundercount + "次");
                    setText("泄露电流：" + LastWcurrent + "μA");
                    record.setLastwcurrent(LastWcurrent);
                    record.setLastthundercount(Thundercount);

                    AddAndUpdate(record);
                }
            } else {
                setText("从设备返回的数据有误！请检查串口！");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            setText("从设备返回的数据有误！请检查串口！");
        }
    }

    @Transactional
    private void AddAndUpdate(Zxdblqsensor record) {
        int alarmLevel = 0;// 报警等级
        String alarmMessage = "";// 报警消息
        // 报警逻辑
        // 这里写报警逻辑
        // 获取数据库中的报警值相关
        if (record.getWcurrentalarmvalue() == null ||
                record.getWcurrentalarmrelievevalue() == null ||
                record.getWcurrentwarnvalue() == null ||
                record.getWcurrentwarnrelievevalue() == null ||
                record.getRcurrentalarmvalue() == null ||
                record.getRcurrentalarmrelievevalue() == null ||
                record.getRcurrentwarnvalue() == null ||
                record.getRcurrentwarnrelievevalue() == null) {
            setText("设备地址" + record.getDeviceaddr() + " 未设置报警值！");
            return;
        }
        List<Integer> array = new ArrayList<>();
        record.setLastwalarmstatus(
                GetAlarmStatus(isnull(record.getLastwcurrent()), isnull(record.getWcurrentalarmvalue()),
                        isnull(record.getWcurrentalarmrelievevalue()), isnull(record.getWcurrentwarnvalue()),
                        isnull(record.getWcurrentwarnrelievevalue()),
                        isnull(record.getLastwalarmstatus()), true, "泄露电流", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastwalarmstatus(), "泄露电流");
        array.add(record.getLastwalarmstatus());
        if (!ad.getBrand().equals("云南德胜")) {
            record.setLastralarmstatus(
                    GetAlarmStatus(isnull(record.getLastrcurrent()), isnull(record.getRcurrentalarmvalue()),
                            isnull(record.getRcurrentalarmrelievevalue()), isnull(record.getRcurrentwarnvalue()),
                            isnull(record.getRcurrentwarnrelievevalue()),
                            isnull(record.getLastralarmstatus()), true, "阻性电流", record.getDevicegroup(),
                            record.getDeviceaddr(),
                            record.getPointname()));
            alarmMessage += GetAlarmMessage(record.getLastralarmstatus(), "阻性电流");
            array.add(record.getLastralarmstatus());
        }

        // record.setLastcwalarmstatus(
        // GetAlarmStatus(isnull(record.getLastcwcurrent()),
        // isnull(record.getWcurrentalarmvalue()),
        // isnull(record.getWcurrentalarmrelievevalue()),
        // isnull(record.getWcurrentwarnvalue()),
        // isnull(record.getWcurrentwarnrelievevalue()),
        // isnull(record.getLastcwalarmstatus()), true, "C相泄露电流",
        // record.getDeviceaddr(),
        // record.getPointname()));
        // alarmMessage += GetAlarmMessage(record.getLastcwalarmstatus(), "C相泄露电流");
        // array.add(record.getLastwalarmstatus());
        alarmLevel = HexUtil.MAX(array);
        record.setLastalarmlevel(alarmLevel);
        record.setLastalarmmessage(alarmMessage);
        record.setLastcommunicationstatus(0);
        record.setLastdatatime(new Date());
        record.setLasthisdatatime(addHistory(record));
        if (zxdblqsensorServiceImpl.Update(record, false) == 0) {
            setText("更新实时数据失败，请检查数据库连接");
        }
    }

    private Date addHistory(Zxdblqsensor sensor) {
        if (sensor != null) {
            if (sensor.getLasthisdatatime() == null) {
                add(sensor);
                return new Date();
            } else {
                long lasttime = 0;
                long nowtime = 0;
                try {
                    lasttime = HexUtil.todate(sensor.getLasthisdatatime()).getTime();
                    nowtime = HexUtil.todate(new Date()).getTime();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                int timersp = 60000;
                if (sensor.getLastalarmlevel() != 0) {
                    timersp = ad.getHisalarmtimersp() * 1000;
                } else {
                    timersp = ad.getHistimersp() * 1000;
                }
                if (lasttime + timersp < nowtime) {
                    add(sensor);
                    return new Date();
                }
            }
        }
        return null;
    }

    private void add(Zxdblqsensor sensor) {
        Zxdblqhistory his = new Zxdblqhistory();
        his.setDeviceaddr(sensor.getDeviceaddr());
        his.setDevicegroup(sensor.getDevicegroup());
        his.setAlarmlevel(sensor.getLastalarmlevel());
        his.setAlarmmessage(sensor.getLastalarmmessage());
        his.setDatatime(sensor.getLastdatatime());
        his.setPointaddr(sensor.getPointaddr());
        his.setPointname(sensor.getPointname());
        his.setStationid(sensor.getStationid());
        his.setCommunicationstatus(sensor.getLastcommunicationstatus());
        // 需要添加自己定义的属性
        his.setWcurrent(sensor.getLastwcurrent());
        his.setRcurrent(sensor.getLastrcurrent());
        int Tcount = sensor.getLastthundercount();
        his.setThundercount(Tcount);
        his.setThundertime(sensor.getLastthundertime1());

        his.setWalarmstatus(sensor.getLastwalarmstatus());
        his.setRalarmstatus(sensor.getLastralarmstatus());
        zxdblqsensorServiceImpl.Add(his);
    }

    public static float parseHex88(String num) {
        int ret = Integer.parseInt(num, 16);
        if (num.length() == 2) {
            return ret;
        } else if (num.length() == 4) {
            ret = ((ret & 0x8000) > 0) ? (ret - 0x10000) : (ret);
            return ret;
        } else {
            throw new NumberFormatException("Wrong length: " + num.length() + ", must be 4.");
        }
    }

    @Async("threadPool")
    public void startSendThread(Appdevice Appdevice) throws Exception {
        issend.put(Thread.currentThread().getId(), true);
        String cstr = "";
        checkType = "crc16";
        String nametype = "";
        int timersp = (int) Math.round(Appdevice.getTimersp() * 1000);
        while (issend.get(Thread.currentThread().getId()) != null) {
            if (addrindex > Appdevice.getAddrmax() || addrindex < Appdevice.getAddrmin())
                addrindex = Appdevice.getAddrmin();
            if (cmdtype == 0) {
                cstr = String.format("%s0400800004", String.format("%02X", addrindex));
                cstr = cstr + CRC16.calcCrc16(cstr);
            }
            // else if(cmdtype==1)
            // {
            // cstr = String.format("%s0400770004", String.format("%02X", addrindex));
            // cstr = cstr + CRC16.calcCrc16(cstr);
            // if(addrindex == Appdevice.getAddrmin())
            // cmdtype =0;
            // }
            LocalDateTime localDateTime = LocalDateTime.now();
            int hour = localDateTime.getHour();
            // if(hour==12)
            // {

            // DateTimeFormatter stf = DateTimeFormatter.ofPattern("yyMMddHHmm");
            // cstr = String.format("%s060082%s", String.format("%02X",
            // addrindex),stf.format(localDateTime));
            // cstr = cstr + CRC16.calcCrc16(cstr);
            // }

            try {
                Send(cstr);
            } catch (Exception EX) {
                setText(EX.toString());
            }
            // setText("向" + Appdevice.getName() + "设备发送指令" + cstr);
            reSend[addrindex]++;
            if (reSend[addrindex] > 3) {
                zxdblqsensorServiceImpl.UpdateStatus(ad, addrindex, 1);
                reSend[addrindex] = 0;
                addrindex++;
            }
            Thread.sleep(timersp);
        }
    }

    // @Async("threadPool")
    // public void startReceiveThread(){
    // isrecv.put(Thread.currentThread().getId(), true);
    // while (isrecv.get(Thread.currentThread().getId()) != null) {
    // //这里根据实际协议替换,解析方法recvCrc16;recvSum();
    // recv();
    // try {
    // Thread.sleep(interval);
    // } catch (InterruptedException e) {
    // e.printStackTrace();
    // }
    // }
    // }
}
